#include "stdafx.h"
#include "AllocateMeshHeirarchy.h"
#include "Mesh.h"

namespace Renderer
{
	void CopyString(const char * input, char ** output)
	{
		if(input)
		{
			UINT length = (UINT)strlen(input) + 1;
			*output = new char[length];
			strcpy_s(*output, length, input);
		}
		else
		{
			*output = NULL;
		}
	}

	HRESULT AllocateMeshHeirarchy::CreateFrame(PCTSTR name, D3DXFRAME **newFrame)
	{
		FrameEx * frame = new FrameEx();

		if(name) 
			CopyString(name, &frame->Name);
		else
			CopyString("$No Name$", &frame->Name);

		frame->pMeshContainer = NULL;
		frame->pFrameSibling = NULL;
		frame->pFrameFirstChild = NULL;
		D3DXMatrixIdentity(&frame->TransformationMatrix);
		D3DXMatrixIdentity(&frame->toRoot);

		*newFrame = frame;

		return D3D_OK;
	}

	HRESULT AllocateMeshHeirarchy::CreateMeshContainer(PCTSTR name, const D3DXMESHDATA * meshData, const D3DXMATERIAL * materials,
		const D3DXEFFECTINSTANCE * effectInstance, DWORD numMaterials, const DWORD * adjacency, ID3DXSkinInfo * skinInfo, 
		D3DXMESHCONTAINER ** newMeshContainer)
	{
		D3DXMESHCONTAINER* meshContainer = new D3DXMESHCONTAINER();
		ZeroMemory(meshContainer, sizeof(D3DXMESHCONTAINER));
		if(name)
			CopyString(name, &meshContainer->Name);
		else
			CopyString("$NoName$", &meshContainer->Name);

		*newMeshContainer = meshContainer;

		if(skinInfo == NULL || meshData->Type != D3DXMESHTYPE_MESH)
			return D3D_OK;

		meshContainer->NumMaterials = numMaterials;
		meshContainer->pMaterials = new D3DXMATERIAL[numMaterials];
		for(DWORD i = 0; i < numMaterials; ++i)
		{
			D3DXMATERIAL * mtrls = meshContainer->pMaterials;
			mtrls[i].MatD3D = materials[i].MatD3D;
			mtrls[i].MatD3D.Ambient = materials[i].MatD3D.Diffuse;

			CopyString(materials[i].pTextureFilename, &mtrls[i].pTextureFilename);
		}

		meshContainer->pEffects = NULL;
		meshContainer->pAdjacency = NULL;

		meshContainer->MeshData.Type = D3DXMESHTYPE_MESH;
		meshContainer->MeshData.pMesh = meshData->pMesh;
		meshContainer->pSkinInfo = skinInfo;
		meshData->pMesh->AddRef();
		skinInfo->AddRef();

		return D3D_OK;

	}

	HRESULT AllocateMeshHeirarchy::DestroyFrame(D3DXFRAME *frameToFree)
	{
		delete [] frameToFree->Name;
		delete frameToFree;

		return D3D_OK;
	}

	HRESULT AllocateMeshHeirarchy::DestroyMeshContainer(D3DXMESHCONTAINER *meshContainerBase)
	{
		delete [] meshContainerBase->Name;
		delete [] meshContainerBase->pAdjacency;
		delete [] meshContainerBase->pEffects;

		for(DWORD i = 0; i < meshContainerBase->NumMaterials; ++i)
		{
			delete [] meshContainerBase->pMaterials[i].pTextureFilename;
		}

		delete [] meshContainerBase->pMaterials;

		ReleaseCOM(meshContainerBase->MeshData.pMesh);
		ReleaseCOM(meshContainerBase->pSkinInfo);

		delete meshContainerBase;

		return D3D_OK;
	}

}